ASM 汇编语言 9

  • Created on 2014-11

教材:《汇编语言》(第二版)王爽 著 清华大学出版社

章十二、内中断

中断:CPU不再接着(刚执行完的指令)向下执行

12.1 内中断的产生
当8086 CPU发生以下情况时,将产生马上处理的中断信息:
     *. 右边数字为中断类型码
(1)除法错误(执行div时产生溢出) - 0
(2)单步执行 - 1
(3)执行into指令 - 4
(4)执行int指令 - 该指令的格式为 int n
          指令中n为byte型立即数,是提供给CPU的中断类型码

12.2 中断处理程序
根据中断类型码,定位相应中断处理程序

12.3 中断向量表
中断向量表,存储256个中断处理程序的 入口地址(CS:IP)
它在内存中存放,对于8086PC机,放在内存地址0处
(在0000:0000~0000:03FF,CS、IP地址分别都是dword,共占4B)

12.4 中断过程
(1)从中断信息中,取得中断类型码 N
(2)标志寄存器的值入栈,pushf
     (因为中断过程中要改变标志寄存器的值,要先将其保存在栈中)
(3)将标志寄存器的第8位 TF 和 第9位 IF 的值 设置为 0
          TF = 0, IF = 0(目的日后详述)
(4)CS 的内容 入栈,push cs
(5)IP 的内容 入栈,push ip
(6)设置中断处理程序的入口地址
          IP = (中断类型码 * 4)     ; 用地址为 中断类型码 * 4 的内存内容 设置IP
          CS = (中断类型码 * 4 + 2)     ; 类上
然后执行中断处理程序

12.5 中断处理程序 使用 iret 指令返回
iret 功能: pop ip     pop cs     popf


12.6 除法错误中断的处理
12.7 编程处理 0 号(除法错误)中断
12.8 安装
12.9 do1
12.10设置中断向量

assume cs:code
code segment
start:
     mov ax, cs
     mov ds, ax
     mov si, offset do0
    
     mov ax, 0
     mov es, ax
     mov di, 200h
     ;0000:0000~0000:03FF 为中断向量表
     ;而0200~02FF还不被其它程序包括OS等使用
     ;可以安全使用
    
     ;传输长度
     mov cx, offset do0end - offset do0
     cld     ;设置传输方向为正
     rep movsb     ;安装程序

    
     ;设置中断向量表
     mov ax, 0
     mov es, ax
     mov word ptr es:[0 * 4], 200h     ;ip
     mov word ptr es:[0 * 4 + 2], 0     ;cs

    
     mov ax, 4c00h
     int 21h
    
do0:
     jmp short do0start
     db 'Overflow!'
do0start:
     ;指向上面定义的那串字符
     mov ax, cs
     mov ds, ax
     mov si, 202h
    
     ;指向显示空间的中间位置
     mov ax, 0b800h
     mov es, ax
     mov di, 12 * 160 + 36 * 2
    
     mov cx, 9
s:
     mov al, [si]
     mov es:[di], al
     inc si
     add di, 2
     loop s

     mov ax, 4c00h
     int 21h
do0end:
     nop

code ends
end start



12.11 单步中断
使 TF = 1CPU将工作于 单步中断 方式下,
执行完这条指令后,就引发单步中断

当然,进入中断处理程序前,设置TF = 0
避免在中断处理程序执行中发生单步中断

12.12 响应中断的特殊情况
在执行完向 ss 寄存器传送数据的指令后
即便发生中断,CPU也不会响应

主要原因:
ss:sp 联合指向栈顶,而对它们的设置应该连续完成。
因为假如设置完ss后被中断,需要压栈保存数据,
此时后续设置sp的语句没有执行,于是中断处理保存了错误的sp
中断恢复后,会导致sp没有指向正确的栈顶

所以设置sp的语句紧跟设置ss的语句!


实验12 编写0号中断的处理程序
编写0号中断的处理程序,使得在出发溢出发生时,
在屏幕中间显示字符串“divide error!”,然后返回到DOS。

类同12.10小节下的程序

assume cs:code
code segment
start:
     mov ax, cs     ;cs 曾错写为 offset do
     mov ds, ax
     mov si, offset do     ;offset do 曾错写为 0
    
     mov ax, 0
     mov es, ax
     mov di, 200h
    
     mov cx, offset do_end - offset do
     cld
     rep movsb
    
     mov word ptr es:[0 * 4], 200h     ;ip
     mov word ptr es:[0 * 4 + 2], 0     ;cs
    
     mov ax, 1000
     mov bh, 1
     div bh
    
     mov ax, 4c00h
     int 21h
    
do:
     mov ax, 0
     mov ds, ax
     mov si, 200h + offset msg - offset do
    
     mov ax, 0b800h
     mov es, ax
     mov di, 12 * 160 + 2 * (40 - (offset do_end - offset msg) / 2)
    
     mov cx, offset do_end - offset msg
s:
     mov al, ds:[si]
     mov es:[di], al
     inc si
     add di, 2
     loop s
    
     mov ax, 4c00h
     int 21h
msg:
     db "divide error!"     ;13字
do_end:
     nop
    
code ends
end start

后记:
1. 趁着对12.10小节的中断处理程序的安装程序还有印象时,重写的。不够独立。
2.竟然对照12.10小节的程序来debug!不能容忍有下次!

0%